﻿using Microsoft.Hadoop.Client;
using Microsoft.Hadoop.MapReduce;
using Microsoft.Hadoop.WebClient.WebHCatClient;
using Microsoft.Hadoop.WebHDFS;
using Microsoft.Hadoop.WebHDFS.Adapters;
using Microsoft.Win32;
using Microsoft.WindowsAzure.Management.HDInsight;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewMaker;
using ViewMaker.Core;
using ViewMaker.Core.Controls;

namespace HDInsightStudio
{

    [View(typeof(HiveStudioView))]
    [ViewProperty(ViewControl.Properties.WindowHeight,400)]
    [ViewProperty(ViewControl.Properties.WindowWidth, 600)]
    public class HiveStudio : JobViewModelBase
    {
        public string InputCommand
        {
            get { return _inputCommand; }
            set { _inputCommand = value; OnPropertyChanged("InputCommand"); }
        }
        private string _inputCommand;

        [View(ViewControlType.TextBox)]
        [ViewProperty(TextBoxViewControl.Properties.IsMultiline, true)]
        [ViewProperty(TextBoxViewControl.Properties.IsReadOnly, true)]
        [ViewProperty(TextBoxViewControl.Properties.GridHeight, "*")]
        [ViewProperty(TextBoxViewControl.Properties.VerticalAlignment, LayoutVerticalAlignment.Stretch)]
        public string Output
        {
            get { return _output; }
            set { _output = value; OnPropertyChanged("Output"); }
        }
        private string _output;

        public MapReduceResult Result
        {
            get { return _result; }
            set { _result = value; }
        }
        private MapReduceResult _result;

        public bool Busy
        {
            get { return _busy; }
            set { _busy = value; OnPropertyChanged(null); }
        }
        private bool _busy;


        private string HomeFolder = "/HiveStudio";

        public HiveStudio():this(DateTime.Now.ToString("yyyyMMddHHmmss"))
        {
        }

        public HiveStudio(string jobId):base(jobId)
        {
            Status = HomeFolder + "/" + jobId + "/Status/";

        }

        public ICommand ExecuteMapReduceCommand
        {
            get { return this.CreateCommand(ExecuteHive, (x)=>!Busy); }
        }
        private void ExecuteHive()
        {
            if (!string.IsNullOrWhiteSpace(InputCommand))
            {

                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += (s, e) =>
                {
                    Busy = true;

                    var hiveJob = new HiveJobCreateParameters()
                    {
                        Query = InputCommand,
                        StatusFolder = Status,
                    };

                    var jobResult = Config.JobClient.CreateHiveJobAsync(hiveJob).WaitForResult();

                    WaitForJobCompletion(jobResult, ProgressProc);
                    Output = ReadOutput();

                    Busy = false;

                };
                worker.RunWorkerAsync();


            }
        }
        private bool ProgressProc(JobDetails job)
        {
            Output = ReadOutput();
            return true;
        }


        protected override void Save()
        {
            JObject data = new JObject{
                { "Type", this.GetType().Name },
                { "InputCommand", InputCommand },
            };
            SaveData(data);
        }

        protected override void Load()
        {
            var data = LoadData();
            if (data == null) return;
            if ((string)data.Property("Type").Value != this.GetType().Name)
            {
                this.ShowMessage("Invalid selected file. " + data.Property("Type").Value);
            }
            else
            {
                this.InputCommand = (string)data.Property("InputCommand").Value;
            }
        }

    }
}
